package com.vichat.task;

import com.alibaba.dubbo.container.spring.SpringContainer;
import com.alibaba.fastjson.JSONObject;
import com.vichat.common.cache.RedisHelper;
import com.vichat.common.constant.GlobalConstant;
import com.vichat.common.util.DateUtil;
import com.vichat.common.util.NumberUtils;
import com.vichat.online.entity.StatOnlineUser;
import com.vichat.online.service.IOnlineService;
import com.vichat.task.service.ITask;
import com.vichat.user.service.IUserService;
import com.vichat.utils.OnlineUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import redis.clients.jedis.ScanResult;

import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * Created by ranjx on 2018/06/29.
 * 处理人员在线数据
 */
@Component("PfmOnlineUserStateTask")
public class PfmOnlineUserStateTask implements ITask {
    private static transient final Logger logger = LoggerFactory.getLogger(PfmOnlineUserStateTask.class);


    @Override
    public String doTask(long cfgTaskId) throws Exception {

        try {
            ApplicationContext ctx = SpringContainer.getContext();
            IUserService userService = (IUserService) ctx.getBean("userService", IUserService.class);
            IOnlineService onlineService = (IOnlineService) ctx.getBean("onlineService", IOnlineService.class);
            //初始化im在线用户
            try {
                OnlineUtil.onlineImUser = onlineService.initOnlineUser();
                int onlineUserNum = OnlineUtil.onlineImUser.size();
                logger.debug("@@@@@@@@@@@@@@@@@初始化在线用" + onlineUserNum);
            } catch (Exception e) {
                logger.error("初始化在线用户数量失", e);
            }
            ExpireUserClearThread expireUserClearThread = new ExpireUserClearThread(onlineService, userService);
            expireUserClearThread.start();

            UserOnlineStateReaderThread userOnlineStateReaderThread = new UserOnlineStateReaderThread(onlineService, userService);
            userOnlineStateReaderThread.start();

        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    class UserOnlineStateReaderThread extends Thread {
        IOnlineService onlineService;
        IUserService userService;

        UserOnlineStateReaderThread(IOnlineService onlineService, IUserService userService) {
            this.onlineService = onlineService;
            this.userService = userService;
        }

        public void run() {
            while (true) {
                try {
                    ScanResult<Map.Entry<String, String>> result;// =  jedis.hscan("hash",DATASOURCE_SELECT);
                    int count = 0;
                    int cursor = 0;
                    do {
                        result = RedisHelper.hscan("USTATE", String.valueOf(cursor));
                        if (result != null) {
                            cursor = Integer.valueOf(result.getStringCursor());
                            for (Map.Entry<String, String> map : result.getResult()) {
                                try {
                                    logger.info(map.getKey() + ":" + map.getValue());//300000357:{"uid":300000357,"time":"2018-11-01 10:27:55","addr":"60.168.132.45:13979"}
                                    long uid = NumberUtils.toLong(map.getKey());
                                    JSONObject json = JSONObject.parseObject(map.getValue());
                                    UserOnlineStateDealThread thread = new UserOnlineStateDealThread(onlineService, userService, json);
                                    OnlineUtil.startUserStateDealer(thread, uid % 10);
                                    RedisHelper.hdel("USTATE", map.getKey());//刪除
                                } catch (Exception e) {
                                    logger.error("Parse USER_STATE Data Error", e);
                                }
                            }
                        }
                    }
                    while (cursor != 0);
                    Thread.sleep(1000 * 5);//处理完毕休息5S

                } catch (Exception e) {
                    e.printStackTrace();
                    logger.error("Redis hsan {USTATE} Error", e);
                }
            }
        }
    }


    class UserOnlineStateDealThread extends Thread {
        IOnlineService onlineService;
        IUserService userService;
        JSONObject ustate;

        UserOnlineStateDealThread(IOnlineService onlineService, IUserService userService, JSONObject json) {
            this.onlineService = onlineService;
            this.userService = userService;
            this.ustate = json;
        }

        public void run() {

            try {
                long uid = ustate.getLongValue("uid");
                String time = ustate.getString("time");
                String address = ustate.getString("addr");
                if (StringUtils.isNotBlank(time)) {
                    Timestamp timestamp = DateUtil.getDateByString(time);

                    if (OnlineUtil.onlineImUser.containsKey(uid)) {
                        StatOnlineUser onlineUser = OnlineUtil.onlineImUser.get(uid);
                        long timeDifference = timestamp.getTime() - onlineUser.getUpTime().getTime();
                        if (timeDifference < 0) {//如果redis是新的数据才处理
                            return;
                        }
                        onlineUser.setLastTime(timestamp);
                        if (timeDifference > 300 * 1000) {//如果时间差有300秒了，则记录下
                            onlineUser.setUpTime(timestamp);
                            userService.updateOnlineState(uid, GlobalConstant.DISPLAY_STATE_ONLINE);
                            onlineService.saveStatOnlineUser(onlineUser);
                        }
                    } else {
                        StatOnlineUser onlineUser = new StatOnlineUser();
                        onlineUser.setImDisplayState(1L);
                        onlineUser.setInTime(timestamp);
                        onlineUser.setUpTime(timestamp);
                        onlineUser.setLastTime(timestamp);
                        onlineUser.setState(1L);
                        onlineUser.setUAddress(address);
                        onlineUser.setPartyId(RedisHelper.getPartyIdByUid(uid));
                        onlineUser.setUid(uid);

                        userService.updateOnlineState(uid, GlobalConstant.DISPLAY_STATE_ONLINE);
                        onlineService.saveStatOnlineUser(onlineUser);
                        OnlineUtil.changeOnlineUser(onlineUser, 1);
                    }

                }


            } catch (Exception e) {
                logger.error("Deal User State Error", e);
            }

        }
    }

    class ExpireUserClearThread extends Thread {
        IOnlineService onlineService;
        IUserService userService;

        ExpireUserClearThread(IOnlineService onlineService, IUserService userService) {
            this.onlineService = onlineService;
            this.userService = userService;
        }

        public void run() {
            while (true) {
                try {
                    Thread.sleep(60 * 1000);
                    //清除过期在线用户
                    long currentTime = System.currentTimeMillis();
                    HashMap<Long, StatOnlineUser> onlineUserCopy = (HashMap<Long, StatOnlineUser>) OnlineUtil.onlineImUser.clone();
                    for (Iterator<StatOnlineUser> iter = onlineUserCopy.values().iterator(); iter.hasNext(); ) {
                        StatOnlineUser onlineUser = iter.next();
                        long timeDiffence = currentTime - onlineUser.getLastTime().getTime();
                        logger.info(timeDiffence + "  " + JSONObject.toJSONString(onlineUser));
                        if (timeDiffence > 300 * 1000) {//如果当前时间和上次更新时间大于5分钟，认为其离线，做离线处理
                            logger.info("!!!!!!!!!!!!!!!!!处理超时用户" + onlineUser.getUid());
                            try {
                                userService.updateOnlineState(onlineUser.getUid(), GlobalConstant.DISPLAY_STATE_OFFLINE);
                            } catch (Exception e) {
                                logger.error("更新在线状态出错，可能用户已经被删除", e);
                            }
                            //onlineUser.setLastTime(new Date(currentTime));
                            onlineService.dealUserOffline(onlineUser);
                            OnlineUtil.changeOnlineUser(onlineUser, -1);
                        }
                    }


                } catch (Exception e) {
                    logger.error("清理过期数据出错", e);
                }
            }
        }
    }


}
